package com.gztms.ordermgnt.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Month;
import cn.hutool.core.date.Quarter;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gztms.enums.AppCodeEnum;
import com.gztms.enums.OrderStatus;
import com.gztms.ordermgnt.mapper.OrderMapper;
import com.gztms.ordermgnt.pojo.Order;
import com.gztms.ordermgnt.pojo.VO.AttractionSale;
import com.gztms.ordermgnt.pojo.VO.DaySale;
import com.gztms.ordermgnt.service.StaticsService;
import com.gztms.travelmgnt.pojo.Attractions;
import com.gztms.travelmgnt.service.AttractionsService;
import com.gztms.utils.MapUtil;
import com.gztms.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Zoey
 * @date 2023/5/24 0:20
 * @Description TODO
 **/
@Service
public class StaticsServiceImpl extends ServiceImpl<OrderMapper, Order> implements StaticsService {

    @Autowired
    private AttractionsService attractionsService;

    @Override
    public ResultUtil getSalesByMonth() {
//        LocalDateTime now = LocalDateTime.now();
//        String year = String.valueOf(now.getYear());
//        QueryWrapper<Order> wrapper = new QueryWrapper<>();
//        wrapper.select("DATE_FORMAT(pay_time, '%Y-%m') AS month", "COUNT(*) AS count", "SUM(total_price) AS amount")
//                .groupBy("DATE_FORMAT(pay_time, '%Y-%m')")
//                .eq("DATE_FORMAT(pay_time, '%Y')", year)
//                .eq("status", OrderStatus.ORDER_PAID);
//        List<Map<String, Object>> maps = baseMapper.selectMaps(wrapper);
//        Map<String, Object> map = new HashMap<>();
//        map.put("salesMonth",maps);
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getStatus,OrderStatus.ORDER_PAID);
        Integer[] totalCount = {0,0,0,0,0,0,0,0,0,0,0,0};
        BigDecimal money = new BigDecimal(0);
        BigDecimal[] totalMoney = {money,money,money,money,money,money,money,money,money,money,money,money};
        List<Order> orders = list(queryWrapper);
        for (Order order : orders) {
            Date payTime = order.getPayTime();
            Month month = DateUtil.monthEnum(payTime);
            int count = order.getCount();

            // 统计
            BigDecimal totalPrice = order.getTotalPrice();
            switch (month) {
                case JANUARY:
                    totalCount[0] += count;
                    totalMoney[0] = totalMoney[0].add(totalPrice);
                    break;
                case FEBRUARY:
                    totalCount[1] += count;
                    totalMoney[1] = totalMoney[1].add(totalPrice);
                    break;
                case MARCH:
                    totalCount[2] += count;
                    totalMoney[2] = totalMoney[2].add(totalPrice);
                    break;
                case APRIL:
                    totalCount[3] += count;
                    totalMoney[3] = totalMoney[3].add(totalPrice);
                    break;
                case MAY:
                    totalCount[4] += count;
                    totalMoney[4] = totalMoney[4].add(totalPrice);
                    break;
                case JUNE:
                    totalCount[5] += count;
                    totalMoney[5] = totalMoney[5].add(totalPrice);
                    break;
                case JULY:
                    totalCount[6] += count;
                    totalMoney[8] = totalMoney[6].add(totalPrice);
                    break;
                case AUGUST:
                    totalCount[7] += count;
                    totalMoney[7] = totalMoney[7].add(totalPrice);
                    break;
                case SEPTEMBER:
                    totalCount[8] += count;
                    totalMoney[8] = totalMoney[8].add(totalPrice);
                    break;
                case OCTOBER:
                    totalCount[9] += count;
                    totalMoney[9] = totalMoney[9].add(totalPrice);
                    break;
                case NOVEMBER:
                    totalCount[10] += count;
                    totalMoney[10] = totalMoney[10].add(totalPrice);
                    break;
                case DECEMBER:
                    totalCount[11] += count;
                    totalMoney[11] = totalMoney[11].add(totalPrice);
                    break;
                default:
                    break;
            }

        }
        Map<String, Object> map = new HashMap<>();
        map.put("countMonth",Arrays.asList(totalCount));
        map.put("moneyMonth",Arrays.asList(totalMoney));
        return ResultUtil.okResult(map);
    }

    @Override
    public ResultUtil getSalesByYear() {
        LocalDateTime now = LocalDateTime.now();
        String year = String.valueOf(now.getYear());
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getStatus,OrderStatus.ORDER_PAID)
                .like(Order::getPayTime,year);
        List<Order> orders = list(queryWrapper);
        BigDecimal totalMoney = new BigDecimal(0);
        int count = 0;
        for (Order order : orders) {
            count += order.getCount();
            totalMoney = totalMoney.add(order.getTotalPrice());
        }

//        QueryWrapper<Order> wrapper = new QueryWrapper<>();
//        wrapper.select("DATE_FORMAT(pay_time, '%Y') AS year", "COUNT(*) AS count", "SUM(total_price) AS amount")
//                .groupBy("DATE_FORMAT(pay_time, '%Y')")
//                .eq("DATE_FORMAT(pay_time, '%Y')", year)
//                .eq("status", OrderStatus.ORDER_PAID);
//        List<Map<String, Object>> maps = baseMapper.selectMaps(wrapper);

        Map<String, Object> map = new HashMap<>();
        map.put("countYear",count);
        map.put("moneyYear",totalMoney);
        return ResultUtil.okResult(map);
    }

    @Override
    public ResultUtil getSalesByQuarter() {
//        LocalDateTime now = LocalDateTime.now();
//        QueryWrapper<Order> wrapper = new QueryWrapper<>();
//        String year = String.valueOf(now.getYear());
//
//
//        wrapper.select("QUARTER(pay_time) AS quarter", "IFNULL(COUNT(id), 0) AS count", "SUM(IFNULL(total_price, 0)) AS amount")
//                .groupBy("quarter")
//                .eq("status", OrderStatus.ORDER_PAID)
//                .eq("DATE_FORMAT(pay_time, '%Y')", year);
//
//        List<Map<String, Object>> maps = baseMapper.selectMaps(wrapper);
//        Map<String, Object> map = new HashMap<>();
//        map.put("sales",maps);
//        map.put("salesQuarter",maps);


        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getStatus,OrderStatus.ORDER_PAID);
        int q1 = 0;
        int q2 = 0;
        int q3 = 0;
        int q4 = 0;
        BigDecimal totalQ1 = new BigDecimal(0);
        BigDecimal totalQ2 = new BigDecimal(0);
        BigDecimal totalQ3 = new BigDecimal(0);
        BigDecimal totalQ4 = new BigDecimal(0);
        List<Order> orders = list(queryWrapper);
        for (Order order : orders) {
            Date payTime = order.getPayTime();
            Quarter quarter = DateUtil.quarterEnum(payTime);
            int count = order.getCount();
            // 统计
            BigDecimal totalPrice = order.getTotalPrice();
            switch (quarter) {
                case Q1:
                    q1 += count;
                    totalQ1 = totalQ1.add(totalPrice);
                    break;
                case Q2:
                    q2 += count;
                    totalQ2 = totalQ2.add(totalPrice);
                    break;
                case Q3:
                    q3 += count;
                    totalQ3 = totalQ3.add(totalPrice);
                    break;
                case Q4:
                    q4 += count;
                    totalQ4 = totalQ4.add(totalPrice);
                    break;
                default:
                    break;
            }
        }

        ArrayList<Integer> count = CollUtil.newArrayList(q1, q2, q3, q4);
        ArrayList<BigDecimal> totalMoney = CollUtil.newArrayList(totalQ1,totalQ2,totalQ3,totalQ4);

        Map<String,Object> map = new HashMap<>();
        map.put("count",count);
        map.put("totalMoney", totalMoney);
        return ResultUtil.okResult(map);
    }

    @Override
    public ResultUtil getSalesTop() {

        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.select("attr_id AS attrId", "SUM(count) AS totalCount","SUM(IFNULL(total_price, 0)) AS totalMoney")
                .groupBy("attr_id")
                .orderByDesc("totalCount")
                .eq("status", OrderStatus.ORDER_PAID)
                .last("LIMIT 10");
       List<Map<String, Object>> list = baseMapper.selectMaps(wrapper);
       List<AttractionSale> attractionSales = list.stream()
                .map(item -> {
                    try {
                        AttractionSale attractionSale = (AttractionSale) MapUtil.mapToObject(item, AttractionSale.class);
                        Attractions attractions = attractionsService.getById(attractionSale.getAttrId());
                        attractionSale.setAttrName(attractions.getName());
                        return attractionSale;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                }).collect(Collectors.toList());
       Map<String,Object> map = new HashMap<>();
       map.put("attractionSales",attractionSales);
       return ResultUtil.okResult(map);
    }

    @Override
    public ResultUtil getSalesByDay() {
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.select("COUNT(*) AS count","SUM(IFNULL(total_price, 0)) AS totalMoney")
                .eq("status", OrderStatus.ORDER_PAID)
                .apply(true, "TO_DAYS(NOW())-TO_DAYS(pay_time) = 0");
        List<Map<String, Object>> maps = baseMapper.selectMaps(wrapper);
        wrapper.clear();

        // 查询所有已取消的订单数量
        wrapper.select("COUNT(*) AS count","SUM(IFNULL(total_price, 0)) AS totalMoney")
                .eq("status", OrderStatus.ORDER_CANCEL)
                .apply(true, "TO_DAYS(NOW())-TO_DAYS(pay_time) = 0");
        List<Map<String, Object>> cancel = baseMapper.selectMaps(wrapper);

        wrapper.clear();
        wrapper.select("COUNT(*) AS count","SUM(IFNULL(total_price, 0)) AS totalMoney")
                .eq("status", OrderStatus.ORDER_UNPAID)
                .apply(true, "TO_DAYS(NOW())-TO_DAYS(pay_time) = 0");
        List<Map<String, Object>> unPaid = baseMapper.selectMaps(wrapper);

        Map<String, Object> map = maps.get(0);
//        DaySale daySale = new DaySale();
//        daySale.setCount((Integer) map.get("count"));
//        daySale.setTotalMoney((BigDecimal) map.get("totalMoney"));
//        daySale.setCancelCount((Integer) cancel.get(0).get("count"));
//        daySale.setCancelMoney((BigDecimal) cancel.get(0).get("totalMoney"));
//        daySale.setUnPaidCount((Integer) unPaid.get(0).get("count"));
        map.put("totalMoney", maps.get(0).get("totalMoney"));
        map.put("cancelCount", cancel.get(0).get("count"));
        map.put("cancelMoney", cancel.get(0).get("totalMoney"));
        map.put("unPaidCount", unPaid.get(0).get("count"));
        map.put("unPaidMoney", unPaid.get(0).get("totalMoney"));
//        try {
//            DaySale daySale = (DaySale) MapUtil.mapToObject(map, DaySale.class);
//            return ResultUtil.okResult(daySale);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return ResultUtil.errorResult(AppCodeEnum.SYSTEM_ERROR);
        return ResultUtil.okResult(map);

    }


}
